package com.shop.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shop.entity.MerchantMerchant;
import com.shop.entity.Point;
import com.shop.mapper.MerchantMerchantMapper;
import com.shop.model.vo.Rsp;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * (MerchantMerchant)表服务接口
 *
 * @author makejava
 * @since 2020-11-21 10:02:40
 */
@Service
@AllArgsConstructor
public class MerchantMerchantService {
    private final MerchantMerchantMapper merchantMerchantMapper;
    private static final Double R = 6378.137d; //地球半径
    private static Double distance1 = 0.0;
    private static Double distance2 = 0.0;


    public Rsp getByCity(Double latitude, Double longitude, String city) {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, city)
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        if (latitude == null) {
            return Rsp.success(list);
        }
        Point pointUser = new Point(latitude, longitude);
        list.forEach(e -> {
            BigDecimal decimal = new BigDecimal(getDistanceByR(pointUser, new Point(Double.parseDouble(e.getMerchantLatitude()), Double.parseDouble(e.getMerchantLongitude()))) + "")
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
            System.out.println(decimal.toString());
            e.setDistance(decimal);
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantSortByScore() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                int sco = (int) (o1.getMerchantScore() - o1.getMerchantScore());
                if (sco == 0) {
                    return o1.getMerchantReachPrice() - o2.getMerchantReachPrice();
                }
                return sco;
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantSortByDistance(Double latitude, Double longitude) {
        Point pointUser = new Point(latitude, longitude);
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                distance1 = getDistanceByR(pointUser, new Point(Double.parseDouble(o1.getMerchantLatitude()), Double.parseDouble(o1.getMerchantLongitude())));
                distance2 = getDistanceByR(pointUser, new Point(Double.parseDouble(o2.getMerchantLatitude()), Double.parseDouble(o2.getMerchantLongitude())));
                int dis = (int) (distance1 - distance2);
                o1.setDistance(new BigDecimal(distance1 + "").setScale(1, BigDecimal.ROUND_HALF_UP));
                o2.setDistance(new BigDecimal(distance2 + "").setScale(1, BigDecimal.ROUND_HALF_UP));
                o1.setAvgTime((int) (distance1 * 1000 / 10.0 / 60));
                o2.setAvgTime((int) (distance2 * 1000 / 10.0 / 60));
                if (dis == 0) {
                    return (int) (distance2 - distance1);
                }
                return dis;
            }

        });
        return Rsp.success(list);
    }

    private static Double radius(Double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 根据经纬度计算距离
     *
     * @param a 地点a
     * @param b 地点b
     * @return 距离
     */
    private static Double getDistanceByR(Point a, Point b) {
        double distance = 0;
        Double latUser = radius(a.getLatitude());
        Double latMer = radius(b.getLatitude());

        double latDistance = latUser - latMer;
        Double lonDistance = radius(a.getLongitude() - b.getLongitude());
        Double sinA = Math.sin(latDistance / 2.0);
        Double sinB = Math.sin(lonDistance / 2.0);

        distance = 2 * R * Math.asin(Math.sqrt(sinA * sinA + Math.cos(latUser) * Math.cos(latMer) * sinB * sinB));
        return distance;

    }

    /**
     * 根据销量排序
     *
     * @return 商户列表
     */
    public Rsp getMerchantBySalesUp() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                int res = o1.getMerchantMonthlySales() - o2.getMerchantMonthlySales();
                if (res == 0) {
                    return o2.getMerchantMonthlySales() - o1.getMerchantMonthlySales();
                }
                return res;
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantBySalesDown() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                return o2.getMerchantMonthlySales() - o1.getMerchantMonthlySales();
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantBySpeedUp() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                BigDecimal res = BigDecimal.ZERO;
                if (StringUtils.isEmpty(o1.getDistance()) && StringUtils.isEmpty(o2.getDistance())) {
                    res = o1.getDistance().divide(BigDecimal.valueOf(o1.getAvgTime()), 1, BigDecimal.ROUND_HALF_UP).subtract(o2.getDistance().divide(BigDecimal.valueOf(o2.getAvgTime()), 1, BigDecimal.ROUND_HALF_UP));
                    if (res.compareTo(BigDecimal.ZERO) == 0) {
                        return o1.getAvgTime() - o2.getAvgTime();
                    }
                    return Integer.parseInt(String.valueOf(res));
                }
                return o1.getAvgTime() - o2.getAvgTime();
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantBySpeedDown() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                if (StringUtils.isEmpty(o1.getDistance()) && StringUtils.isEmpty(o2.getDistance())) {
                    BigDecimal res = o2.getDistance().divide(BigDecimal.valueOf(o2.getAvgTime()), 1, BigDecimal.ROUND_HALF_UP).subtract(o1.getDistance().divide(BigDecimal.valueOf(o1.getAvgTime()), 1, BigDecimal.ROUND_HALF_UP));
                    if (res.compareTo(BigDecimal.ZERO) == 0) {
                        return o2.getAvgTime() - o1.getAvgTime();
                    }
                    return Integer.parseInt(String.valueOf(res));
                }
                return o2.getAvgTime() - o1.getAvgTime();
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantByReachPriceDown() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                long price1 = o1.getDistance().divide(BigDecimal.valueOf(3), 1, BigDecimal.ROUND_HALF_UP).setScale(0, BigDecimal.ROUND_UP).longValue();
                long price2 = o2.getDistance().divide(BigDecimal.valueOf(3), 1, BigDecimal.ROUND_HALF_UP).setScale(0, BigDecimal.ROUND_UP).longValue();
                o1.setDistributionPrice(price1);
                o2.setDistributionPrice(price2);
                return (int) (price2 - price1);
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantByReachPriceUp() {
        List<MerchantMerchant> list = merchantMerchantMapper.selectList(new QueryWrapper<MerchantMerchant>()
                .lambda().eq(MerchantMerchant::getCity, "武汉")
                .eq(MerchantMerchant::getMerchantStatus, "1")
                .eq(MerchantMerchant::getExamineStatus, "1"));
        list.sort(new Comparator<MerchantMerchant>() {
            @Override
            public int compare(MerchantMerchant o1, MerchantMerchant o2) {
                long price1 = o1.getDistance().divide(BigDecimal.valueOf(3), 1, BigDecimal.ROUND_HALF_UP).setScale(0, BigDecimal.ROUND_UP).longValue();
                long price2 = o2.getDistance().divide(BigDecimal.valueOf(3), 1, BigDecimal.ROUND_HALF_UP).setScale(0, BigDecimal.ROUND_UP).longValue();
                if (!StringUtils.isEmpty(price1) && !StringUtils.isEmpty(price2)) {
                    o1.setDistributionPrice(price1);
                    o2.setDistributionPrice(price2);
                    return (int) (price1 - price2);
                }
                return o1.getMerchantReachPrice() - o2.getMerchantReachPrice();
            }
        });
        return Rsp.success(list);
    }

    public Rsp getMerchantById(Integer id) {
        return Rsp.success(merchantMerchantMapper.getById(id));
    }
}
